/****************************************************************************************/
/* MediaFrame is an Open Source streaming media platform in Java                        */
/* which provides a fast, easy to implement and extremely small applet                  */
/* that enables to view your audio/video content without having                         */
/* to rely on external player applications or bulky plug-ins.                           */
/*                                                                                      */
/*--------------------------------------------------------------------------------------*/
/*                                                                                      */
/* "CryptedInputStream.java"															*/
/*                                                                                      */
/*--------------------------------------------------------------------------------------*/
/*                                                                                      */
/* We changed a lot of code and added a lot of functionality.							*/
/* This includes, but not limited to, the following changes:							*/
/* 1. The project was renamed to MediaFrame;											*/
/* 2. The connection speed detection procedure was added;								*/
/* 3. The JavaScript API functions were added;											*/
/* 4. The pre and post image support functionality was added;							*/
/* 5. The ability to save movie into the local disk was added;							*/
/* 6. The inner buffer for a movie file was added;										*/
/* 7. The click-through functionality was added;    									*/
/* 8. The .zip files support was added;    												*/
/* 9. The realtime feedback agent functionality was added.    							*/
/* For the full list of the current functionality please visit the following web page:	*/
/* http://mediaframe.org/																*/
/*    																					*/
/* 06 Jul 2002 - 19 Dec 2004 Konstantin Belous, Oleg Lebedev							*/
/*																						*/
/*--------------------------------------------------------------------------------------*/
/*                                                                                      */
/* This program is free software; you can redistribute it and/or modify it under the    */
/* terms of the GNU General Public License as published by the Free Software            */
/* Foundation; either version 2 of the License, or (at your option) any later version.  */
/*                                                                                      */
/* This program is distributed in the hope that it will be useful, but WITHOUT ANY      */
/* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      */
/* PARTICULAR PURPOSE. See the GNU General Public License for more details.             */
/*                                                                                      */
/* You should have received a copy of the GNU General Public License along with this    */
/* program; (See "LICENSE.GPL"). If not, write to the Free Software Foundation, Inc.,   */
/* 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.                            */
/*                                                                                      */
/*--------------------------------------------------------------------------------------*/
/*                                                                                      */
/* If the program runs as Java applet it isn't "interactive" in the sense of the GNU    */
/* General Public License. So paragraph 2c doesn't apply.                               */
/*                                                                                      */
/****************************************************************************************/
package mediaframe.mpeg1;

import java.io.*;

/**
 * The <code>CryptedInputStream</code> class implements decryption
 * function of the MPEG stream.
 */
public final class CryptedInputStream extends FilterInputStream {

	/** The current index in the encryption key. */
	private int encryption_index;
	/** The array of bytes (encryption key) which are used for encription of the movie stream. */ 
	private byte[] encryption_key;

	/**
	 * Constructor of the <code>CryptedInputStream</code> class.
	 * @param in the MPEG input stream which is decrypted.
	 * @throws Exception raises if an error occurs during initialization.
	 */
	public CryptedInputStream(InputStream in) throws Exception {
		super(in);
		try {
			encryption_key = (byte[])Class.forName("mediaframe.mpeg4.LicenseManager").getMethod(
				"getEncryptionKey", new Class[0]).invoke(null, new Object[0]);
		} catch (Throwable ex) {
			throw new Exception("Unable to load the encryption key");
		}
	}

	/**
	 * Reads one byte from the input stream
	 * and decrypts it using xor 0x55 operation.
	 * @return readed and decrypted byte.
	 * @throws IOException if an I/O error occurs.
	 */
	public int read() throws IOException {
		int result = super.read();		
		if(result > 0) {
			result ^= encryption_key[encryption_index ++];
			if(encryption_index == encryption_key.length) {
				encryption_index = 0;					
			}
		}		
		return result;
	}

	/**
	 * Reads n bytes from the input stream into the buffer <code>b</code>
	 * and decrypts them using xor 0x55 operation
	 * @param b the buffer into which the data is read.
	 * @return the number of bytes read into the buffer or -1 if the end of the file is reached.
	 * @throws IOException if an I/O error occurs.
	 */
	public int read(byte[] b) throws IOException {
		return read(b, 0, b.length);
	}

	/**
	 * Reads <code>len</code> bytes from the input stream into the buffer <code>b</code>
	 * starting from the offset <code>off</code>
	 * and decrypts them using xor 0x55 operation
	 * @param b the buffer into which the data is read.
	 * @param off the start offset in the array b.
	 * @param len the number of the bytes to read.
	 * @return the number of bytes read into the buffer or -1 if the end of the file is reached.
	 * @throws IOException if an I/O error occurs.
	 */
	public int read(byte[] b, int off, int len) throws IOException {
		int result = super.read(b, off, len);
		if(result > 0) {
			for(int i = off; i < off + result; i ++) {
				b[i] ^= 0x55;
			}
		}
		return result;
	}

}